From 16d3e72a8fd71de9df1fab8ef8c791d5f7666ad0 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sun, 4 Jan 2015 20:59:43 -0500 Subject: [PATCH] git option in config should be an enumeration The option in ~/.cargo/config is now called `vcs` and has the following options: "git", "hg", and "none". This corresponds to the options for the --vcs argument to `cargo new`. This also fixes detection for hg repositories. Previously, we only tried to discover if the working directory was contained in a git repository. If it was, we would skip creating a git repo. Now, we check if the working directory is contained in either a git or mecurial repo. If it is, we skip creating a new repo. Fixes #1116 --- src/bin/new.rs | 24 +---------- src/cargo/ops/cargo_new.rs | 81 +++++++++++++++++++++++++++----------- src/cargo/ops/mod.rs | 2 +- src/cargo/util/vcs.rs | 5 +++ src/doc/config.md | 4 +- 5 files changed, 68 insertions(+), 48 deletions(-) diff --git a/src/bin/new.rs b/src/bin/new.rs index 2fb43478c..bf355ccab 100644 --- a/src/bin/new.rs +++ b/src/bin/new.rs @@ -1,34 +1,16 @@ use std::os; -use rustc_serialize::{Decodable, Decoder}; use cargo::ops; use cargo::core::MultiShell; use cargo::util::{CliResult, CliError}; -#[deriving(Show, PartialEq)] -enum VersionControl { Git, Hg, NoVcs } - -impl> Decodable for VersionControl { - fn decode(d: &mut D) -> Result { - Ok(match try!(d.read_str()).as_slice() { - "git" => VersionControl::Git, - "hg" => VersionControl::Hg, - "none" => VersionControl::NoVcs, - n => { - let err = format!("could not decode '{}' as version control", n); - return Err(d.error(err.as_slice())); - } - }) - } -} - #[deriving(RustcDecodable)] struct Options { flag_verbose: bool, flag_bin: bool, flag_travis: bool, arg_path: String, - flag_vcs: Option, + flag_vcs: Option, } pub const USAGE: &'static str = " @@ -55,9 +37,7 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult let Options { flag_travis, flag_bin, arg_path, flag_vcs, .. } = options; let opts = ops::NewOptions { - no_git: flag_vcs == Some(VersionControl::NoVcs), - git: flag_vcs == Some(VersionControl::Git), - hg: flag_vcs == Some(VersionControl::Hg), + version_control: flag_vcs, travis: flag_travis, path: arg_path.as_slice(), bin: flag_bin, diff --git a/src/cargo/ops/cargo_new.rs b/src/cargo/ops/cargo_new.rs index 1fa52c7d1..6291d54be 100644 --- a/src/cargo/ops/cargo_new.rs +++ b/src/cargo/ops/cargo_new.rs @@ -2,24 +2,41 @@ use std::os; use std::io::{mod, fs, File}; use std::io::fs::PathExtensions; +use rustc_serialize::{Decodable, Decoder}; + use git2::Config; use util::{GitRepo, HgRepo, CargoResult, human, ChainError, config, internal}; use core::shell::MultiShell; +#[deriving(Copy, Show, PartialEq)] +pub enum VersionControl { Git, Hg, NoVcs } + pub struct NewOptions<'a> { - pub no_git: bool, - pub git: bool, - pub hg: bool, + pub version_control: Option, pub travis: bool, pub bin: bool, pub path: &'a str, } +impl> Decodable for VersionControl { + fn decode(d: &mut D) -> Result { + Ok(match try!(d.read_str()).as_slice() { + "git" => VersionControl::Git, + "hg" => VersionControl::Hg, + "none" => VersionControl::NoVcs, + n => { + let err = format!("could not decode '{}' as version control", n); + return Err(d.error(err.as_slice())); + } + }) + } +} + struct CargoNewConfig { name: Option, email: Option, - git: Option, + version_control: Option, } pub fn new(opts: NewOptions, _shell: &mut MultiShell) -> CargoResult<()> { @@ -41,28 +58,38 @@ pub fn new(opts: NewOptions, _shell: &mut MultiShell) -> CargoResult<()> { }) } -fn existing_git_repo(path: &Path) -> bool { - GitRepo::discover(path).is_ok() +fn existing_vcs_repo(path: &Path) -> bool { + GitRepo::discover(path).is_ok() || HgRepo::discover(path).is_ok() } fn mk(path: &Path, name: &str, opts: &NewOptions) -> CargoResult<()> { let cfg = try!(global_config()); let mut ignore = "/target\n".to_string(); - let no_git = !opts.git && (opts.no_git || cfg.git == Some(false)); - let in_existing_git_repo = existing_git_repo(&path.dir_path()); + let in_existing_vcs_repo = existing_vcs_repo(&path.dir_path()); if !opts.bin { ignore.push_str("/Cargo.lock\n"); } - if opts.hg { - try!(HgRepo::init(path)); - try!(File::create(&path.join(".hgignore")).write(ignore.as_bytes())); - } else if no_git || in_existing_git_repo { - try!(fs::mkdir(path, io::USER_RWX)); - } else { - try!(GitRepo::init(path)); - try!(File::create(&path.join(".gitignore")).write(ignore.as_bytes())); - } + let vcs = match (opts.version_control, cfg.version_control, in_existing_vcs_repo) { + (None, None, false) => VersionControl::Git, + (None, Some(option), false) => option, + (Some(option), _, false) => option, + (_, _, true) => VersionControl::NoVcs, + }; + + match vcs { + VersionControl::Git => { + try!(GitRepo::init(path)); + try!(File::create(&path.join(".gitignore")).write(ignore.as_bytes())); + }, + VersionControl::Hg => { + try!(HgRepo::init(path)); + try!(File::create(&path.join(".hgignore")).write(ignore.as_bytes())); + }, + VersionControl::NoVcs => { + try!(fs::mkdir(path, io::USER_RWX)); + }, + }; let (author_name, email) = try!(discover_author()); // Hoo boy, sure glad we've got exhaustivenes checking behind us. @@ -134,7 +161,7 @@ fn global_config() -> CargoResult { let mut cfg = CargoNewConfig { name: None, email: None, - git: None, + version_control: None, }; let cargo_new = match user_configs.get("cargo-new") { None => return Ok(cfg), @@ -158,12 +185,20 @@ fn global_config() -> CargoResult { })).0.to_string()) } }; - cfg.git = match cargo_new.get("git") { + cfg.version_control = match cargo_new.get("vcs") { None => None, - Some(git) => { - Some(try!(git.boolean().chain_error(|| { - internal("invalid configuration for key `cargo-new.git`") - })).0) + Some(vcs) => { + let vcs_str = try!(vcs.string().chain_error(|| { + internal("invalid configuration for key `cargo-new.vcs`") + })).0; + let version_control = match vcs_str.as_slice() { + "git" => VersionControl::Git, + "hg" => VersionControl::Hg, + "none"=> VersionControl::NoVcs, + _ => return Err(internal("invalid configuration for key `cargo-new.vcs`")), + }; + + Some(version_control) } }; diff --git a/src/cargo/ops/mod.rs b/src/cargo/ops/mod.rs index 53ade356e..79140527a 100644 --- a/src/cargo/ops/mod.rs +++ b/src/cargo/ops/mod.rs @@ -6,7 +6,7 @@ pub use self::cargo_rustc::{Context, LayoutProxy}; pub use self::cargo_rustc::Platform; pub use self::cargo_rustc::{BuildOutput, BuildConfig, TargetConfig}; pub use self::cargo_run::run; -pub use self::cargo_new::{new, NewOptions}; +pub use self::cargo_new::{new, NewOptions, VersionControl}; pub use self::cargo_doc::{doc, DocOptions}; pub use self::cargo_generate_lockfile::{generate_lockfile}; pub use self::cargo_generate_lockfile::{update_lockfile}; diff --git a/src/cargo/util/vcs.rs b/src/cargo/util/vcs.rs index f18d6dcc4..7847a75bb 100644 --- a/src/cargo/util/vcs.rs +++ b/src/cargo/util/vcs.rs @@ -23,4 +23,9 @@ impl HgRepo { try!(try!(process("hg")).arg("init").arg(path_str).exec()); return Ok(HgRepo) } + pub fn discover(path: &Path) -> CargoResult { + try!(try!(process("hg")).arg("root").cwd(path.clone()).exec_with_output()); + return Ok(HgRepo) + } } + diff --git a/src/doc/config.md b/src/doc/config.md index fa6a69e57..e7b6e33e2 100644 --- a/src/doc/config.md +++ b/src/doc/config.md @@ -45,8 +45,8 @@ name = "..." email = "..." # By default `cargo new` will initialize a new git repository. This key can be -# set to `false` to disable this behavior. -git = true +# set to `none` to disable this behavior. +vcs = "none" # For the following sections, $triple refers to any valid target triple, not the # literal string "$triple", and it will apply whenever that target triple is -- 2.30.2